package com.ruoyi.service.impl;

import com.ruoyi.dto.PaymentDto;
import com.ruoyi.dto.WeChatRefundDto;
import com.ruoyi.framework.config.SmartParkingCloudConfig;
import com.ruoyi.framework.config.WxPayConfig;
import com.ruoyi.service.IWeChatService;
import com.wechat.pay.java.core.cipher.RSASigner;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 微信Service业务层处理
 * 
 * @author dongdong
 * @date 2025-08-20
 */
@Slf4j
@Service
public class WeChatServiceImpl implements IWeChatService {

    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private RefundService refundService;
    @Autowired
    private RSASigner rsaSigner;
    @Autowired
    private JsapiService jsapiService;

    /**
     * 微信支付
     * @param paymentDto
     * @return
     */
    public Map<String, String> weChatPay(PaymentDto paymentDto) {
        String appId = "wx".equals(paymentDto.getLy())? SmartParkingCloudConfig.APPID_XCX:SmartParkingCloudConfig.APPID;
        try {
            PrepayRequest request = new PrepayRequest();

            // 设置金额
            Amount amount = new Amount();
            amount.setTotal(paymentDto.getAmount().multiply(BigDecimal.valueOf(100)).intValue());
            request.setAmount(amount);

            // 设置支付者
            Payer payer = new Payer();
            payer.setOpenid(paymentDto.getUniqueId());
            request.setPayer(payer);

            // 设置基本参数
            request.setAppid(appId);
            request.setMchid(wxPayConfig.getMchId());
            request.setDescription(paymentDto.getBody());
            request.setNotifyUrl(wxPayConfig.getNotifyUrl());
            request.setOutTradeNo(paymentDto.getOrderNo());

            // 调用预支付
            PrepayResponse response = jsapiService.prepay(request);

            // 返回支付参数
            long timestamp = System.currentTimeMillis() / 1000;
            String nonceStr = UUID.randomUUID().toString().replace("-", "");
            String packageStr = "prepay_id=" + response.getPrepayId();

            // 构造签名字符串
            String message = appId + "\n" +
                    timestamp + "\n" +
                    nonceStr + "\n" +
                    packageStr + "\n";

            // 生成签名
            String paySign = rsaSigner.sign(message).getSign();

            Map<String, String> result = new HashMap<>();
            result.put("appId", appId);
            result.put("timeStamp", String.valueOf(timestamp));
            result.put("nonceStr", nonceStr);
            result.put("package", packageStr);
            result.put("signType", "RSA");
            result.put("paySign", paySign);
            return result;
        } catch (Exception e) {
            log.error("{} 微信支付创建失败: {}", paymentDto.getOrderNo(), e.getMessage());
            throw new RuntimeException("支付失败，请联系客服");
        }
    }

    @Override
    public Map<String, Object> weChatRefund(WeChatRefundDto weChatRefundDto) {
        try {
            /* ---------- 1. 组装请求 ---------- */
            CreateRequest req = new CreateRequest();
            req.setTransactionId(weChatRefundDto.getTransNo());
            req.setOutTradeNo(weChatRefundDto.getOrderNo());
            req.setOutRefundNo(weChatRefundDto.getRefundNo());
            req.setReason(weChatRefundDto.getReason());
            req.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
            AmountReq amount = new AmountReq();
            // 微信：单位分
            amount.setTotal(weChatRefundDto.getOrderAmount().multiply(BigDecimal.valueOf(100)).longValue());
            amount.setRefund(weChatRefundDto.getRefundAmount().multiply(BigDecimal.valueOf(100)).longValue());
            amount.setCurrency("CNY");
            req.setAmount(amount);

            /* ---------- 2. 调用退款接口 ---------- */
            Refund resp = refundService.create(req);

            /* ---------- 3. 封装结果 ---------- */
            Map<String, Object> result = new HashMap<>();
            result.put("refundId", resp.getRefundId());   // 微信退款单号
            result.put("outRefundNo", resp.getOutRefundNo());
            result.put("status", resp.getStatus());       // SUCCESS/PROCESSING/ABNORMAL
            result.put("successTime", resp.getSuccessTime());
            return result;
        } catch (Exception e) {
            log.error("{} 微信退款创建失败: {}", weChatRefundDto.getRefundNo(), e.getMessage());
            throw new RuntimeException("退款失败，请联系客服");
        }
    }
}
